package com.app.ryjy.util;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.app.ryjy.model.ResponseEntity;
import com.app.ryjy.enums.ApiCodeEnum;
import com.app.ryjy.model.Ab01Po;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

import static com.app.ryjy.util.Sm2Util.pem2PrivateKey;
import static com.app.ryjy.util.Sm2Util.pem2PublicKey;

/**
 * 如意就业接口请求类
 */
public class RyjyHttpUtils {

    public static final String BASE_URL = "https://ggjyfw.rst.gansu.gov.cn:8443/terminal/ryjyApi/request/getData.do";
    public static final String CHANNEL_CODE = "jqs";
    private static ECPrivateKeyParameters privateKey = null;
    private static ECPublicKeyParameters publicKey = null;
    // 创建一个固定大小为4的线程池
    private static ExecutorService executor = new ThreadPoolExecutor(5, 20,
            5000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>());

    static {
        //注：这个位置是放置密钥的地方，根据密钥放置的位置获取
        String privateKeyFilePath = "/szkey/private.keystore";
        String publicKeyFilePath = "/szkey/public.keystore";
        try {
            privateKey = pem2PrivateKey(privateKeyFilePath);
            publicKey = pem2PublicKey(publicKeyFilePath);
        } catch (Exception e) {
            throw new RuntimeException("获取密钥失败");
        }
    }

    /**
     * 统一请求
     *
     * @param apiCode 接口编号
     * @param params  请求参数实体类
     */
    private static void request(ApiCodeEnum apiCode, Object params) {
        //请求耗时
        long start = System.currentTimeMillis();
        Map requestData = new HashMap<>();
        requestData.put("data", encrypt(params));
        requestData.put("channelCode", CHANNEL_CODE);
        requestData.put("apiCode", apiCode);
        String resultencrypt = HttpUtil.post(BASE_URL, requestData);
        ResponseEntity responseEntity = responseHandler(resultencrypt);
        System.out.print("接口编号:" + apiCode + ", ");
        System.out.print("请求耗时:" + (System.currentTimeMillis() - start) + "ms, ");
        System.out.println("请求结果:" + JSONUtil.toJsonStr(responseEntity));
    }

    /**
     * 请求参数公钥加密
     *
     * @param jsonObj
     * @return
     */
    private static String encrypt(Object jsonObj) {

        String jsonData = JsonFactory.bean2json(jsonObj);
        String encrypt = null;
        try {
            encrypt = Sm2Util.encrypt(publicKey, jsonData);
        } catch (Exception e) {
            throw new RuntimeException("加密失败:" + e);
        }
        return encrypt;
    }

    /**
     * 响应参数私钥解密
     *
     * @param respone
     * @return
     */
    private static ResponseEntity responseHandler(String respone) {

        Map resultMap = JsonFactory.json2bean(respone, Map.class);
        String result;
        try {
            if ("1" .equals(resultMap.get("code"))) {
                result = Sm2Util.decrypt(privateKey, ((Map) resultMap.get("resultData")).get("data").toString());
            } else {
                result = Sm2Util.decrypt(privateKey, resultMap.get("message").toString());
            }
        } catch (Exception e) {
            throw new RuntimeException("解密失败:" + e);
        }
        return JSONObject.parseObject(result, ResponseEntity.class);
    }

    public static void main(String[] args) {
        //方式一(推荐)
        List<Ab01Po> obParamList = new ArrayList<>();
        Ab01Po ab01Po = new Ab01Po();
        ab01Po.setAab001_szgj(new BigDecimal(10000005));
        ab01Po.setAab998("91620102670822775R");
        ab01Po.setAab003("91620102670822775R");
        ab01Po.setAab004("兰州海神安全防范技术有限公司");
        ab01Po.setAab008(new Date());
        ab01Po.setAab019("10");
        ab01Po.setAae119("1");
        ab01Po.setYae421("1");
        ab01Po.setYae100("54");
        ab01Po.setAae100("1");
        obParamList.add(ab01Po);
        asyncSubmit(ApiCodeEnum.companyAdd, obParamList);
    }

    /**
     * 异步报送
     *
     * @param apiCodeEnum
     * @param obParamList
     */
    public static void asyncSubmit(ApiCodeEnum apiCodeEnum, Object obParamList) {
        try {
            executor.submit(() -> {
                request(apiCodeEnum, obParamList);
            });
            executor.shutdown();
        } catch (Exception e) {
            System.out.println("异步请求失败:" + e);
            e.printStackTrace();
        }
    }
}
